﻿using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;

namespace TraceView.UI.Entities
{
    public sealed class ApplicationInfo : BaseEntity
    {
        private string _applicationName;
        private string _searchString;
        private int _newItemsCount;
        private readonly AllItemsCollection _allItems;
        private readonly PinnedItemsCollection _pinnedItems;
        private readonly RecentItemsCollection _recentItems;
        private readonly TraceItemCollection _traceItems;

        public ApplicationInfo(string applicationName, IFilterCollectionMatchCriteria[] filters)
        {
            _applicationName = applicationName;
            _traceItems = new TraceItemCollection();
            _allItems = new AllItemsCollection(_traceItems, filters);
            _pinnedItems = new PinnedItemsCollection();
            _recentItems = new RecentItemsCollection(_traceItems, filters);
            _traceItems.CollectionChanged += TraceItemsCollectionChanged;
        }

        public AllItemsCollection AllItems
        {
            get { return _allItems; }
        }

        public PinnedItemsCollection PinnedItems
        {
            get { return _pinnedItems; }
        }

        public RecentItemsCollection RecentItems
        {
            get { return _recentItems; }
        }

        public TraceItemCollection TraceItems
        {
            get { return _traceItems; }
        }

        public string SearchString
        {
            get { return _searchString; }
            set { SetProperty(() => SearchString, ref _searchString, value); }
        }

        public string ApplicationName
        {
            get { return _applicationName; }
            set { SetProperty(() => ApplicationName, ref _applicationName, value); }
        }

        public int NewItemsCount
        {
            get { return _newItemsCount; }
            set { SetProperty(() => NewItemsCount, ref _newItemsCount, value); }
        }

        private void TraceItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                var newItem = (TraceItem)e.NewItems[0];
                newItem.PropertyChanged += TraceItemPropertyChanged;
                RecentItems.Add(newItem);
                AllItems.Add(newItem);
            }
        }

        private void TraceItemPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsPinned")
            {
                var item = (TraceItem)sender;
                if (item.IsPinned)
                    PinnedItems.Add(item);
                else
                    PinnedItems.Remove(item);
            }
        }
    }

    public sealed class ApplicationCollection : BaseEntityCollection<ApplicationInfo>
    {
        private readonly IFilterCollectionMatchCriteria[] _filters;

        public ApplicationCollection(IFilterCollectionMatchCriteria[] filters)
        {
            _filters = filters;
        }

        public void Add(TraceItem traceItem)
        {
            ApplicationInfo application =
                this.FirstOrDefault(
                    app => app.ApplicationName.Equals(traceItem.ApplicationName, StringComparison.OrdinalIgnoreCase));
            if (application == null)
            {
                application = new ApplicationInfo(traceItem.ApplicationName, _filters);
                Add(application);
            }
            application.TraceItems.Add(traceItem);
        }
    }
}